package com.guanghua.brick.html.tag;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.guanghua.brick.html.Constant;
import com.guanghua.brick.util.IConfig;
import com.guanghua.brick.util.XmlReader;

public class WebPageHeaderTag extends BodyTagSupport {
	
	private static Log logger = LogFactory.getLog(WebPageHeaderTag.class);
	
	
	//控制是否需要输出将request的attr序列化到js中
	private boolean serialAttribute = false;
	public void setSerialAttribute(boolean sa) {this.serialAttribute = sa;}
	public boolean isSerialAttribute() {return this.serialAttribute;}
	
	private boolean serialParameter = true;
	public boolean isSerialParameter() {return serialParameter;}
	public void setSerialParameter(boolean serialParameter) {this.serialParameter = serialParameter;}
	
	
	public int doEndTag() throws JspException {
		//out page head
		String head = getWebPageHead();
		try {
			pageContext.getOut().println(head);
		} catch (IOException e) {
			logger.error("io exception on print head", e);
		}
		
		//put web_app_context
		String context = WebAppContextTag.getWebAppContext(pageContext);
		pageContext.getRequest().setAttribute(Constant.WEB_APP_CONTEXT_KEY, context);
		return BodyTagSupport.EVAL_PAGE;
	}
	
	private String getWebPageHead() {
		StringBuffer s = new StringBuffer();
		//获取web app context
		String context = WebAppContextTag.getWebAppContext(pageContext);
		s.append("<script language=\"javascript\">var globeWebAppContext = \"").append(context).append("\";</script>\n");
		//序列化request到js
		if (this.serialParameter) {
			String req = serialRequestParameter();
			s.append("<script language=\"javascript\">var globeRequestParameter = \"").append(req.replace("\"", "\\\"")).append("\";</script>\n");
		}
		
		if (this.serialAttribute) {
			//序列化request attr到js
			String req = serialRequestAttribute();
			s.append("<script language=\"javascript\">var globeRequestAttribute = \"").append(req.replace("\"", "\\\"")).append("\";</script>\n");
		}
		
		String head = (String)pageContext.getServletContext().getAttribute(Constant.WEB_BRICK_HEAD);
		if (head != null) s.append(head);
		
		head = (String)pageContext.getServletContext().getAttribute(Constant.WEB_PAGE_HEAD);
		if (head == null) {
			try {
				StringBuffer h = new StringBuffer();
				
				//构造reader
				XmlReader reader = new XmlReader(pageContext.getServletContext().getRealPath("/WEB-INF/brick.web.xml"), true);
				
				//读取css文件
				IConfig[] c = reader.readByTagName("css");
				for (int i = 0; i < c.length; i ++) {
					String folder = c[i].getAttribute("folder");
					Iterator<String> its = findValidFile(new File(pageContext.getServletContext().getRealPath(folder)), c[i].getText()).iterator();
					while (its.hasNext()) {
						h.append("<link type=\"text/css\" rel=\"stylesheet\" href=\"")
						.append(context)
						.append(folder)
						.append("/")
						.append(its.next())
						.append("\"/>\n");
					}
				}
				
				//读取js文件
				c = reader.readByTagName("js");
				for (int i = 0; i < c.length; i ++) {
					String folder = c[i].getAttribute("folder");
					Iterator<String> its = findValidFile(new File(pageContext.getServletContext().getRealPath(folder)), c[i].getText()).iterator();
					while (its.hasNext()) {
						h.append("<script language=\"javascript\" src=\"")
						.append(context)
						.append(folder)
						.append("/")
						.append(its.next())
						.append("\"></script>\n");
					}
				}
				
				head = h.toString();
				pageContext.getServletContext().setAttribute(Constant.WEB_PAGE_HEAD, head);
			} catch (Exception e) {
				logger.error("parse xml /web-inf/brick.web.xml to find page head error", e);
			}
			s.append(head);
		} else
			s.append(head);
		//默认的js request对象
		s.append("<script language=\"javascript\">var request = new Request();</script>\n");
		return s.toString();
	}
	
	
	/**
	 * 用来返回某个文件夹下的那些文件名称符合pattern模版的方法
	 * @param folder
	 * @param pattern
	 * @return
	 */
	private List<String> findValidFile(File folder, String pattern) {
		List<String> ret = new ArrayList<String>();
		if (folder != null && folder.exists() && folder.isDirectory()) {
			File[] f = folder.listFiles();
			for (int i = 0; i < f.length; i ++) {
				if (Pattern.matches(pattern, f[i].getName())) {
					ret.add(f[i].getName());
				}
			}
		}
		return ret;
	}
	
	/**
	 * 将request param序列化成query string的形式
	 * 以便于js生成request对象
	 * @return
	 */
	private String serialRequestParameter() {
		Map map = pageContext.getRequest().getParameterMap();
		Iterator i = map.keySet().iterator();
		StringBuffer r = new StringBuffer();
		while (i.hasNext()) {
			String key = i.next().toString();
			String[] values = (String[])map.get(key);
			for (int j = 0; j < values.length; j ++) {
				r.append("&")
				.append(key.replace("&", "&amp;").replace("=", "&el;"))
				.append("=")
				.append(values[j].replace("&", "&amp;").replace("=", "&el;").replace("\n", "\\n").replace("\r", "\\r"));
			}
		}
		return (r.length()==0)?"":r.substring(1);
	}
	
	/**
	 * 将request attribute序列化成query string的形式
	 * 以便于js生成request对象
	 * @return
	 */
	private String serialRequestAttribute() {
		Enumeration e = pageContext.getRequest().getAttributeNames();
		StringBuffer r = new StringBuffer();
		while (e.hasMoreElements()) {
			String key = e.nextElement().toString();
			Object value = pageContext.getRequest().getAttribute(key);
			r.append("&")
			.append(key.replace("&", "&amp;").replace("=", "&el;"))
			.append("=")
			.append(value.toString().replace("&", "&amp;").replace("=", "&el;"));
		}
		return (r.length()==0)?"":r.substring(1);
	}
	
}
